package service

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/pquerna/otp/totp"
	"zhonghui/console/warehouse/cfgx"
	"zhonghui/console/warehouse/dbx/cache_main"
	"zhonghui/console/warehouse/dbx/db_zh_kernel"
	"zhonghui/console/warehouse/envx"
	"zhonghui/console/warehouse/helperx"
	"zhonghui/console/warehouse/modelx/model_zh_kernel"

	"zhonghui/console/structs"
)

// SignInWithCode 根据code来登录
func SignInWithCode(c context.Context, code string) (uint, error) {
	user := model_zh_kernel.ConsoleManager{}

	// 使用code获取公众号用户信息
	// resp, err := ms_official_account.WebOauthInfo(c, config.Cfg().GetString("console.oauth.app_id"), code)
	// if err != nil {
	// 	return 0, err
	// }

	// 根据open_id查询用户
	// if err := db_zh_kernel.ClientCtx(c).Where("open_id = ?", resp.Data.OpenId).Take(&user).Error; err != nil {
	// 	return 0, err
	// }

	if user.IsActive != 1 {
		return 0, errors.New("该用户已被禁用")
	}

	return user.ID, nil
}

// SignInWithPhone 根据手机号来登录
func SignInWithPhone(c context.Context, phone string, password string) (uint, error) {
	user := model_zh_kernel.ConsoleManager{}
	if err := db_zh_kernel.ClientCtx(c).Where("phone = ?", phone).Take(&user).Error; err != nil {
		return 0, err
	}

	if user.IsActive != 1 {
		return 0, errors.New("该用户已被禁用")
	}

	// 获取app key
	key := cfgx.Cfg().GetString("console.app_key")

	// 解密已有的密码
	wantPassword, err := helperx.AesDecrypt(user.Password, key[:16], key[16:], false)
	if err != nil {
		return 0, err
	}

	// 对比
	if wantPassword != password {
		return 0, errors.New("密码错误")
	}

	return user.ID, nil
}

// NeedOtp 判断是否需要OTP
func NeedOtp(userId uint, clientUid string) bool {
	return false
	if !envx.InProd() {
		return true
	}
	return cache_main.Client().Get(context.Background(), fmt.Sprintf("otp-valid-limit-uid-%d-client-%s", userId, clientUid)).Val() == ""
}

// IsValidOtp 验证otp正确性，如正确则缓存起来
func IsValidOtp(otpStr, otpSecret string, userId uint, clientUid string) bool {
	return true
	if !envx.InProd() {
		return true
	}

	// fmt.Println(user.OtpSecret, otpStr, totp.Validate(otpStr, user.OtpSecret))

	// 验证otp
	if !totp.Validate(otpStr, otpSecret) {
		return false
	}

	// 缓存otp 7天内不用再次输入
	cache_main.Client().Set(context.Background(), fmt.Sprintf("otp-valid-limit-uid-%d-client-%s", userId, clientUid), "yes", time.Hour*7*24)

	return true
}

// MakeOtp 生成OTP
func MakeOtp(phone string) (string, string, error) {
	k, err := totp.Generate(totp.GenerateOpts{
		Issuer:      "yxc_console",
		AccountName: phone,
	})

	if err != nil {
		return "", "", err
	}

	return k.URL(), k.Secret(), nil
}

// IssueToken 生成token
func IssueToken(userId uint, expireSecond int64) (string, error) {
	claim := &structs.TokenClaims{}
	claim.ExpiresAt = time.Now().Unix() + expireSecond
	claim.Issuer = "yxc_console_passport"
	claim.IssuedAt = time.Now().Unix()
	claim.UserID = userId

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)

	return token.SignedString([]byte(cfgx.Cfg().GetString("console.app_key")))
}

// GetUserFromToken 根据token获取用户信息
func GetUserFromToken(tokenString string) *model_zh_kernel.ConsoleManager {
	claim := &structs.TokenClaims{}

	token, err := jwt.ParseWithClaims(tokenString, claim, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		return []byte(cfgx.Cfg().GetString("console.app_key")), nil
	})

	if err != nil {
		return nil
	}

	if _, ok := token.Claims.(*structs.TokenClaims); ok && token.Valid {
		user := model_zh_kernel.ConsoleManager{}
		if err := db_zh_kernel.Client().Where("id = ? and is_active = 1", claim.UserID).Take(&user).Error; err != nil {
			return nil
		}

		return &user
	} else {
		return nil
	}
}

// BindWithCode 绑定微信
func BindWithCode(c context.Context, userId uint, code string) error {
	// 使用code获取公众号用户信息
	// resp, err := ms_official_account.WebOauthInfo(c, config.Cfg().GetString("console.oauth.app_id"), code)
	// if err != nil {
	// 	return err
	// }

	// 根据open_id查询用户
	user := model_zh_kernel.ConsoleManager{}
	if err := db_zh_kernel.ClientCtx(c).Where("id = ?", userId).Take(&user).Error; err != nil {
		return err
	}

	if user.OpenID != nil {
		return errors.New("该账户已绑定过微信")
	}

	// 上传头像
	// oc, err := warehouse_service.OssClient("normal")
	// if err != nil {
	// 	return err
	// }

	// path, err := oc.OssUploadWxAvatar(resp.Data.Avatar, "fund")
	// if err != nil {
	// 	return err
	// }

	// 保存
	// user.OpenId = &resp.Data.OpenId
	// user.Nickname = resp.Data.Nickname
	// user.Avatar = path
	// if err := db_zh_kernel.ClientCtx(c).Save(&user).Error; err != nil {
	// 	return err
	// }

	return nil
}
